/**
 * @file bull_hal_drv_flash.c
 * @brief 
 * @author yejing (yejh@gongniu.cn)
 * @version 1.0
 * @date 2024-05-11
 * 
 * Copyright 2021-2023 GongNiu Inc. All Rights Reserved.
 * 
 */


#include "bull_hal_drv_flash.h"


#include "nvs_flash.h"
#include "esp_log.h"

static const char* FLASH_TAG = "flash_drv";
/***********************************************************
*************************micro define***********************
***********************************************************/




/***********************************************************
*************************variable define********************
***********************************************************/
const esp_partition_t *kv_flash_part     = NULL;
const esp_partition_t *dowload_part      = NULL;

#define PART_NUM                        ( 4 )

typedef struct 
{
    BULL_FLASH_PART_ENUM   part_type;
    const esp_partition_t *flash_part;

}BULL_FLASH_PART_LIST_T;


BULL_FLASH_PART_LIST_T flash_part_list[ PART_NUM ] = { 0 };


/***********************************************************
*************************function define********************
***********************************************************/
static OPERATE_RET bull_hal_drv_flash_init(void)
{

    kv_flash_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,ESP_PARTITION_SUBTYPE_ANY, "kv_flash");
    if (kv_flash_part == NULL) {
        ESP_LOGE( FLASH_TAG, "find kv_flash partition fail!");
        return OPRT_COM_ERROR;
    }
    ESP_LOGI( FLASH_TAG,"kv_flash_part offset_addr:0x%lx, size:0x%lx", kv_flash_part->address, kv_flash_part->size );

    flash_part_list[ KV_FLASH_PART ].part_type = KV_FLASH_PART;
    flash_part_list[ KV_FLASH_PART ].flash_part = kv_flash_part;

#if defined(CONFIG_C200_PROJECT)

    const esp_partition_t *dowload_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,ESP_PARTITION_SUBTYPE_ANY, "dowload");
    if (dowload_part == NULL) {
        ESP_LOGE( FLASH_TAG, "find dowload partition fail!");
        return OPRT_OK;
    }
    ESP_LOGI( FLASH_TAG,"dowload offset_addr:0x%lx, size:0x%lx", dowload_part->address, dowload_part->size );


    flash_part_list[ DOWLOAD_PART ].part_type = DOWLOAD_PART;
    flash_part_list[ DOWLOAD_PART ].flash_part = dowload_part;

#endif

    return OPRT_OK;
}


/**
 * @brief read data from flash
 * 
 * @param[in]       offset_addr        flash offset_address
 * @param[out]      dst         pointer of buffer
 * @param[in]       size        size of buffer
 * @return int 0=成功，非0=失败
 */
int bull_hal_drv_flash_read( BULL_FLASH_PART_ENUM part,const unsigned int offset_addr, unsigned char *dst, const unsigned int size)
{
    if (NULL == dst) {
        return OPRT_INVALID_PARM;
    }
    
    if ( flash_part_list[ part ].flash_part == NULL ) {

        if (OPRT_OK != bull_hal_drv_flash_init()) {
            return OPRT_COM_ERROR;
        }
    }

    if ( OPRT_OK != esp_partition_read( flash_part_list[ part ].flash_part, offset_addr, dst, size ) ){

        return OPRT_COM_ERROR;
    }

    return OPRT_OS_ADAPTER_OK;
}

/**
 * @brief write data to flash
 * 
 * @param[in]       offset_addr        flash offset_address
 * @param[in]       src         pointer of buffer
 * @param[in]       size        size of buffer
 * @return int 0=成功，非0=失败
 */
int bull_hal_drv_flash_write(BULL_FLASH_PART_ENUM part,const unsigned int offset_addr, const unsigned char *src, const unsigned int size)
{
    if (NULL == src) {
        return OPRT_INVALID_PARM;
    }

    if ( flash_part_list[ part ].flash_part == NULL ) {

        if (OPRT_OK != bull_hal_drv_flash_init()) {
            return OPRT_COM_ERROR;
        }
    }

    if(OPRT_OK != esp_partition_write(flash_part_list[ part ].flash_part, offset_addr, src, size)) {

        return OPRT_COM_ERROR;
    }

	return OPRT_OS_ADAPTER_OK;
}


/**
 * @brief erase flash block
 * 
 * @param[in]       offset_addr        flash block offset_address
 * @param[in]       size        size of flash block
 * @return int 0=成功，非0=失败
 */
int bull_hal_drv_flash_erase(uint8_t part,const unsigned int offset_addr, const unsigned int size)
{

    if ( flash_part_list[ part ].flash_part == NULL ) {

        if (OPRT_OK != bull_hal_drv_flash_init()) {
            return OPRT_COM_ERROR;
        }
    }

    if(OPRT_OK != esp_partition_erase_range(flash_part_list[ part ].flash_part, offset_addr,size)) {

        return OPRT_COM_ERROR;
    }

    return OPRT_OS_ADAPTER_OK;
}
